Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ECS] Modify ELB listener rules other than defaults without adding config #4733

Merged
merged 9 commits into from
Dec 27, 2023

Conversation

t-kikuc
Copy link
Member

@t-kikuc t-kikuc commented Dec 21, 2023

What this PR does / why we need it:

Modifying listener rules which is not the default rule without specifying in app.pipecd.config, unlike #4726.

Which issue(s) this PR fixes:

Fixes #4725

Does this PR introduce a user-facing change?: no

  • How are users affected by this change: no
  • Is this breaking change: no
  • How to migrate (if breaking change): no

** A short explanation **

If the ELB and app.pipecd.yaml are as below, the rules that will be modified are rule-A1,rule-B1 and rule-B2
since they have the same target groups as app.pipecd.yaml.

ELB-X
|-- Listener-A
|    |-- rule-A1 (default)
|        |-- targetGroup-p
|        |-- targetGroup-c
|-- Listener-B
    |-- rule-B1 (default)
    |    |-- targetGroup-p
    |    |-- targetGroup-c
    |-- rule-B2   [path-pattern: /xxx/*]
    |    |-- targetGroup-p
    |    |-- targetGroup-c
    |-- rule-B3   [path-pattern: /yyy/*]
        |-- targetGroup-x
        |-- targetGroup-y

app.pipecd.yaml:

apiVersion: pipecd.dev/v1beta1
kind: ECSApp
spec:
  input:
    targetGroups:
      primary:
        targetGroupArn: arn:aws:elasticloadbalancing:ap-northeast-1:<account-id>:targetgroup/xxx/yyy1 # targetGroup-p
      canary:
        targetGroupArn: arn:aws:elasticloadbalancing:ap-northeast-1:<account-id>:targetgroup/xxx/yyy2 # targetGroup-c

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>
Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>
Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>
Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>
@t-kikuc t-kikuc changed the title Ecs elb modify rules [ECS] Modify ELB listener rules other than defaults without adding config Dec 21, 2023
Copy link

codecov bot commented Dec 21, 2023

Codecov Report

Attention: 41 lines in your changes are missing coverage. Please review.

Comparison is base (847b578) 30.84% compared to head (fd13dff) 30.84%.
Report is 10 commits behind head on master.

Files Patch % Lines
pkg/app/piped/platformprovider/ecs/client.go 0.00% 41 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4733      +/-   ##
==========================================
- Coverage   30.84%   30.84%   -0.01%     
==========================================
  Files         221      222       +1     
  Lines       25993    26037      +44     
==========================================
+ Hits         8018     8030      +12     
- Misses      17325    17357      +32     
  Partials      650      650              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@t-kikuc
Copy link
Member Author

t-kikuc commented Dec 21, 2023

/review

Copy link
Contributor

PR Analysis

Main theme

ECS Load Balancer Rule Modification

PR summary

The PR changes the approach for modifying ECS load balancer rules by describing ECS rules and subsequently modifying them based on certain conditions. It introduces a check to only modify rules that have the same target groups as defined in the new `RoutingTrafficConfig`.

Type of PR

Enhancement

PR Feedback:

General suggestions

The PR enhances the rule modification logic of ECS load balancers by being more selective in the rules it updates, which seems like a good improvement for accuracy and potentially efficiency. To further improve the code, consider handling possible edge cases and addressing any minor code quality concerns, such as variable declaration placement.

Code feedback

- relevant file: `pkg/app/piped/platformprovider/ecs/client.go`
  suggestion: |
    Consider moving the declaration of `var modifiedActions []elbtypes.Action` outside of the for-loop to avoid re-declaration every loop iteration. Although it is scoped within the for-loop, it's not dependent on the loop iteration and could be reused which may aid in readability.
  relevant line: |
    `+			var modifiedActions []elbtypes.Action`

- relevant file: `pkg/app/piped/platformprovider/ecs/routing_traffic.go`
  suggestion: |
    Ensure that you handle potential null pointer dereferences when working with AWS SDK objects. In the `hasSameTargets` method, add null checks for `forwardActionTargets[i].TargetGroupArn` before dereferencing it to prevent runtime panics. (important)
  relevant line: |
    `+		return *forwardActionTargets[i].TargetGroupArn < *forwardActionTargets[j].TargetGroupArn`

- relevant file: `pkg/app/piped/platformprovider/ecs/routing_traffic.go`
  suggestion: |
    Implement a guard clause in the `hasSameTargets` method for early return if `c` or `forwardActionTargets` are nil to prevent unnecessary sorting or comparison and enhance code clarity. (medium)
  relevant line: |
    `+	if len(c) != len(forwardActionTargets) {`

Security concerns:

no

The PR does not introduce changes that are directly related to common security issues. It primarily deals with load balancer rule modifications and does not involve user input handling, database operations, or other areas typically associated with security vulnerabilities like SQL injection, XSS, or CSRF.

@t-kikuc
Copy link
Member Author

t-kikuc commented Dec 22, 2023

@moko-poi @nnnkkk7
Does this PR satisfy your usecases?

Comment on lines 35 to 47
// Sort so that the both slices have the same target groups.
sort.Slice(c, func(i, j int) bool {
return c[i].TargetGroupArn < c[j].TargetGroupArn
})
sort.Slice(forwardActionTargets, func(i, j int) bool {
return *forwardActionTargets[i].TargetGroupArn < *forwardActionTargets[j].TargetGroupArn
})

for i := range c {
if c[i].TargetGroupArn != *forwardActionTargets[i].TargetGroupArn {
return false
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of sorting both, then iterating through, using an extra map with TargetGroupArn as key could provide a better performance. It's a more straightforward approach.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@khanhtc1202 Thanks! I'll try

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@khanhtc1202
I fixed on 727e13c

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>
})
if err != nil {
return fmt.Errorf("error describing listener %s: %w", listenerArn, err)
return fmt.Errorf("failed to describe rules %s: %w", listenerArn, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return fmt.Errorf("failed to describe rules %s: %w", listenerArn, err)
return fmt.Errorf("failed to describe rules of listener %s: %w", listenerArn, err)

TargetGroupArn: aws.String(routingTrafficCfg[1].TargetGroupArn),
Weight: aws.Int32(int32(routingTrafficCfg[1].Weight)),
for _, rule := range describeRulesOutput.Rules {
var modifiedActions []elbtypes.Action
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var modifiedActions []elbtypes.Action
modifiedActions := make([]elbtypes.Action, 0, len(rule.Actions))

@khanhtc1202
Copy link
Member

LGTM with some nits 👍

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>
@t-kikuc
Copy link
Member Author

t-kikuc commented Dec 26, 2023

@khanhtc1202
Thank you for reviewing, I fixed two

khanhtc1202
khanhtc1202 previously approved these changes Dec 26, 2023
Copy link
Member

@khanhtc1202 khanhtc1202 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great improvement 👍

@khanhtc1202
Copy link
Member

@ffjlabo plz check 👀👀

Comment on lines 128 to 129
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ffjlabo Thank you so much! I fixed

Comment on lines 33 to 42
cMap := make(map[string]bool)
for _, item := range c {
cMap[item.TargetGroupArn] = true
}

for _, target := range forwardActionTargets {
if !cMap[*target.TargetGroupArn] {
return false
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] It would be nice to use struct{} empty struct :)
This is more efficient because it does not allocate memory.

Suggested change
cMap := make(map[string]bool)
for _, item := range c {
cMap[item.TargetGroupArn] = true
}
for _, target := range forwardActionTargets {
if !cMap[*target.TargetGroupArn] {
return false
}
}
cMap := make(map[string]struct{})
for _, item := range c {
cMap[item.TargetGroupArn] = struct{}{}
}
for _, target := range forwardActionTargets {
if _, ok := cMap[*target.TargetGroupArn]; !ok {
return false
}
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ffjlabo Thank you so much! I fixed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ffjlabo
I fixed again to use tc:=tc as you suggested instead of tc:=testcase
because I found an article that recommends to use the same name.

https://go.dev/wiki/CommonMistakes

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>
Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>
ffjlabo
ffjlabo previously approved these changes Dec 27, 2023
Copy link
Member

@ffjlabo ffjlabo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>
Copy link
Member

@khanhtc1202 khanhtc1202 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@t-kikuc t-kikuc merged commit 8c9876a into pipe-cd:master Dec 27, 2023
11 of 13 checks passed
@t-kikuc
Copy link
Member Author

t-kikuc commented Jan 31, 2024

I'll add the below diagrams to the doc later.

  1. Previously, only the default rule was controlled during deployments:

    case-1

  2. Now piped can also control the rules other than the default:

    case-2

  3. Besides, piped controls all rules that have the common target groups:

    case-3

nnnkkk7 pushed a commit to nnnkkk7/pipecd that referenced this pull request Feb 1, 2024
…nfig (pipe-cd#4733)

* Add a func of comparing target groups

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>

* Modify ModifyListeners to edit rules other than default

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>

* Modify comments

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>

* Use ModifyLister to modify the default rules

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>

* Use map to compare target groups

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>

* Fix log and use make()

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>

* Refactored to memory efficient

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>

* Fix reference of loop var of testcases

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>

* Modify loop variable name in test

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>

---------

Signed-off-by: t-kikuc <tkikuchi07f@gmail.com>
@github-actions github-actions bot mentioned this pull request Feb 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[ECS] Support modifying listener rules other than defaults
3 participants